#ifndef _ODN_WORLD_WORLD_H
#define _ODN_WORLD_WORLD_H

//Engine headers
#include "odn_world_Entity.h"

//Standard library headers
#include <vector>

//TODO: See if can make this a variable instead
#define SECTOR_WIDTH 100
#define SECTOR_HEIGHT 100
#define SECTOR_SIZE Vector3D(SECTOR_WIDTH, SECTOR_HEIGHT)

using ouden::basic::Vector3D;

namespace ouden
{
	namespace world
	{
		
		class ODN_World
		{
			
		public:
			
			//Singleton instance function
			static ODN_World* Instance()
			{
				static ODN_World e;
				return &e;
			}
			
			/*
			//Set the size of the sectors used to divide up the world
			void setSectorSize(Vector3D size)
			{
				
				//Store the sector size
				sector_size = size;
				
				//Delete the sector array and recreate it with the new dimensions
				delete[] sectors;
				sectors = new std::vector<ODN_Entity*>[sector_size[0]][sector_size[1]];
				
			}
			*/
			
			bool Update(float TimeStep)
			{
				
				for (int i=0;i<entities.size();i++) {
					
					entities[i]->Update(TimeStep);
					
				}	
				
			}
			
			bool Draw()
			{
				
				for (int i=0;i<entities.size();i++) {
					
					entities[i]->Draw();
					
				}
				
			}
			
			//TODO: Check this function for e parameter working 
			ODN_Entity* addEntity(ODN_Entity* e)
			{
				/*
				//Create a new instance of the entity
				ODN_Entity* newEntity = new e;
				
				//Add the entity to the list
				entities.push_back(newEntity);
				
				return newEntity;
				*/
				
				entities.push_back(e);
				return e;
				
			}
			
			void killEntitity(ODN_Entity* e)
			{
				
				//Create a new iterator to store the position of the entity
    			std::vector<ODN_Entity*>::iterator index;
				
				//Find the entity in the list
				index = std::find(entities.begin(), entities.end(), e);
				
				//TODO: Possibly look into finding a different way to do this
				
				//Delete the entity
				delete e;
				e = 0;  //TODO: Make sure this is working

				//Remove the entity from the array
    			entities.erase(index);
				
			}
			
			//TODO: Put into cpp file
			//Allocates all entities into sectors for quick lookup
			void Sectorise()
			{
				
				//TODO: Clear sectors but leave static entities
				
				//Loop through entities
				for (int i=0;i<entities.size();i++) {
					
					//Check if the object is alive and interactive
					if (entities[i]->isAlive() && entities[i]->isInteractive()) {
						
						int px = int(entities[i]->pos[0]);
						int py = int(entities[i]->pos[1]);
						
						//Calculate number of sectors entity spreads across
						Vector3D sector_spread = entities[i]->boundingbox / SECTOR_SIZE;
						
						//Loop across sector spread
						for (int x = int(px - sector_spread[0]);x < int(px + sector_spread[0]);x++) {
							for (int y = int(py - sector_spread[1]);y < int(py + sector_spread[1]);y++) {
								
								//Add the entity to the sector
								sectors[x][y].push_back(entities[i]);
								
							}
						}
						
					}
					
				}
				
			}
		
		private:
			
			//Constructor and destructor
			ODN_World()		{}
			~ODN_World()
			{
				
				//Delete all the entities
			    while (entities.size())
				{
					delete entities.back();
					entities.pop_back();
				}
	
				//Clear the list of entities
				entities.clear();
				
			}
			
			//Array of world entities
			std::vector<ODN_Entity*> entities;
			
			//Sectors, two dimensional array of vectors of pointers to entities
			std::vector<ODN_Entity*> sectors[SECTOR_WIDTH][SECTOR_HEIGHT];
			
			//Sector variables
			//Vector3D sector_size;
			
			
		};
		
		//Return the singleton instance of the world
		ODN_World* getWorld();
		
	} //namespace world
} //namespace ouden

#endif //_ODN_WORLD_WORLD_H
